<template>
    <div class="cutom-tree-container">
        <Tree v-bind="$attrs" :data="treeData" :render="renderContent" class="custom-tree" :select-node="true" :show-checkbox="false" :style="treeStyle" :expand-node="false"></Tree>
    </div>
</template>

<script>
import { resolveComponent } from '@vue/runtime-core';
export default {
    props: {
        treeStyle: {
            type: String,
            required: false
        },
        checkedIds: {
            type: Array,
            required: false,
            default: []
        },
        data: {
            type: Array,
            required: true,
        }
    },
    data () {
        return {
            dataList: [],
            treeData: [],
            treeDataMap: new Map(),
            checkedData: [],
            isRendering: true
        }
    },
    watch: {
        checkedIds: {
            handler (ids) {
                let timer;
                // 是否正在渲染
                if (this.isRendering) {
                    timer = setInterval(() => {
                        console.log("render检测", this.isRendering);
                        if (!this.isRendering) {
                            this.handleCheckItems(ids);
                            clearInterval(timer);
                        }
                    }, 50)
                }
                else {
                    this.handleCheckItems(ids);
                }
            },
        },
        data: {
            immediate: true,
            handler (data) {
                if (!data || !data.length) return;
                this.initTreeData(data);
            }
        }
    },
    created () {
        if (this.data && this.data.length) {
            this.initTreeData(this.data);
        }
    },
    computed: {
        getTreeData () {
            const data = this.data.map(function (item) {
				return {
					title: item.title,
					id: item.id,
					parentId: item.parentId,
                    hasChecked: false,
                    indeterminate: false
				}
			});
            const Nodes = [];
			data.forEach(item => {
				const parentId = item.parentId;
				if (!parentId) return Nodes.push(item);
				const parent = data.find(function (item) {
					return parentId === item.id;
				});
				if (!parent) return;
				const children = parent.children;
				if (children) {
					children.push(item);
				} else {
					parent.children = [item];
				}
			});
			Nodes.forEach((item) => {
				item.expand = true;
			});
            this.treeData = Nodes;
            return Nodes;
        }
    },
    methods: {
        async initTreeData (data = this.data) {
            this.isRendering = true;
            let dataList = data.map(item => {
                // this.treeDataMap.set(item.id, item);
                return {
                    ...item,
                    hasChecked: false,
                    hasIndeterminate: false,
                    hasSelectd: false
                };
            });
            let parentMap = new Map(),
                rootNode = dataList.find(item => {
                    return !item.parentId;
                });
            for (let i = 0; i < dataList.length; i ++) {
                if (!dataList[i].parentId) {
                    continue;
                }
                let item = dataList[i];
                let parentArray = parentMap.get(item.parentId);
                if (parentArray) {
                    parentMap.set(item.parentId, parentArray.concat([item]));
                }
                else {
                    parentMap.set(item.parentId, [item]);
                }
            }
            rootNode.children = setChildren(rootNode, parentMap);
            function setChildren (item, map) {
                let children = map.get(item.id);
                if (!children) return null;
                children.map(childItem => {
                    childItem.children = setChildren(childItem, parentMap);
                });
                return children;
            }
            rootNode.expand = true;
            // 遍历treeData,将数据全部copy到map中
            let treeMap = new Map();
            setMap(rootNode);
            function setMap(nowItem) {
                treeMap.set(nowItem.id, nowItem);
                if (nowItem.children) {
                    nowItem.children.forEach(item => {
                        setMap(item);
                    });
                }
            }
            this.treeDataMap = treeMap;
            // 需要加异步，否则会堆栈溢出 原因未知，应该是iview渲染有bug
            await setTimeout(() => {
                this.treeData = [rootNode];
            }, 1);
            this.isRendering = false;
        },
        findChildren (dataList, parentId) {
            return dataList.filter(item => {
                return item.parentId == parentId;
            });
        },
        handleCheckItems (ids) {
            this.checkedData = ids;
            ids.forEach(id => {
                let item = this.treeDataMap.get(id);
                if (!item) return;
                item.hasSelectd = true;
                
                if (!item.children) {
                    item.hasChecked = true;
                    this.setParent(item, true);
                }
            });
        },
        renderContent (h, { root, node, data }) {
            let item = data;
            return h("span", {
                style: "padding: 5px 0;"
            }, [
                h(resolveComponent("Checkbox"), {
                    modelValue: item.hasChecked,
                    indeterminate: item.hasIndeterminate,
                    trueValue: true,
                    falseValue: false,
                    // on-change会触发原生事件，onOn-change才能得到iview事件
                    "onOn-change": (value) => {
                        item.hasChecked = value;
                        item.hasIndeterminate = false;
                        this.handleCheckChange(item, value);
                    }
                }),
                h("span", {
                    class: "margin-left-5",
                    onClick: () => {
                        data.expand = !data.expand;
                    }
                }, data.title)
            ]);
        },
        handleCheckChange (item, value) {
            // console.log("checkChange", item.title, item, value);
            this.setChildren(item, value);
            this.setParent(item, value);
            let check = [],
                indeterminate = [];
            this.treeDataMap.forEach(item => {
                if (item.hasChecked) check.push(item.id);
                if (item.hasIndeterminate) indeterminate.push(item.id);
            });
            this.$emit("on-check-change", value, item, check, indeterminate);
        },
        setChildren (item, value) {
            if (item.children) {
                item.children.forEach(childItem => {
                    childItem.hasChecked = value;
                    childItem.hasIndeterminate = false;
                    if (childItem.children) {
                        this.setChildren(childItem, value);
                    }
                });
            }
        },
        setParent (item, value) {
            let parent = this.treeDataMap.get(item.parentId);
            if (!parent) return;
            // console.log("parent", parent.title);
            let checked = [],
                selected = [],
                indeterminate = [],
                childrenLength = parent.children.length;
            parent.children.forEach(childItem => {
                if (childItem.hasChecked) checked.push(childItem);
                if (childItem.hasIndeterminate) indeterminate.push(childItem);
                if (childItem.hasSelectd) selected.push(childItem);
            });
            // 子级没有选中的
            if (checked.length == 0) {
                // 子级没有半选的
                if (indeterminate.length == 0) {
                    parent.hasIndeterminate = false;
                    parent.hasSelectd = false;
                }
                // 子级有半选的
                else {
                    parent.hasIndeterminate = true;
                    parent.hasSelectd = true;
                }
                parent.hasChecked = false;
            }
            // 子级全选中
            else if (checked.length == childrenLength) {
                parent.hasChecked = true;
                parent.hasIndeterminate = false;
                parent.hasSelectd = true;
            }
            // 子级有选中，但没有全选中
            else {
                parent.hasChecked = false;
                parent.hasIndeterminate = true;
                parent.hasSelectd = true;
            }
            // console.log("setParent", parent);
            this.setParent(parent, value);
        },
    }
}
</script>

<style>

</style>